package com.tebiecloud.api.gateway.server.oauth2;

import com.tebiecloud.common.constants.ResultEnum;
import lombok.Data;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
import reactor.core.publisher.Mono;

/**
 * Redis认证管理器
 * @Author: tebie
 * @Date: 2019-08-09 11:38
 */
@Data
public class RedisAuthenticationManager implements ReactiveAuthenticationManager {

    private TokenStore tokenStore;

    public RedisAuthenticationManager(TokenStore tokenStore) {
        this.tokenStore = tokenStore;
    }

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        return Mono.justOrEmpty(authentication)
                .filter(a -> a instanceof BearerTokenAuthenticationToken)
                .cast(BearerTokenAuthenticationToken.class)
                .map(BearerTokenAuthenticationToken::getToken)
                .flatMap((token -> {
                    OAuth2Authentication oAuth2Authentication = this.tokenStore.readAuthentication(token);
                    if(oAuth2Authentication==null){
                        return Mono.error(new InvalidTokenException(ResultEnum.INVALID_TOKEN.getMessage()));
                    }else{
                        return Mono.just(oAuth2Authentication);
                    }
                }))
                .cast(Authentication.class);
    }

}
